package org.jet.emall.rbac.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.jet.emall.common.restful.result.CommonPage;
import org.jet.emall.rbac.dto.AdminPrivilegeDTO;
import org.jet.emall.rbac.dto.AdminRoleDTO;
import org.jet.emall.rbac.po.AdminPrivilegeView;
import org.jet.emall.rbac.po.AdminRole;
import org.jet.emall.rbac.po.AdminRolePrivilege;
import org.jet.emall.rbac.po.AdminUserRole;
import org.jet.emall.rbac.service.mp.IAdminPrivilegeViewService;
import org.jet.emall.rbac.service.mp.IAdminRolePrivilegeService;
import org.jet.emall.rbac.service.mp.IAdminRoleService;
import org.jet.emall.rbac.service.mp.IAdminUserRoleService;
import org.jet.emall.rbac.service.tool.TreeTool;
import org.jet.emall.rbac.transfer.AdminPrivilegeDtoTransfer;
import org.jet.emall.rbac.transfer.AdminRoleDtoTransfer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.IntStream;


/**
 * @author xiaozai
 * @version 1.0
 * @date 2020-04-05 20:10
 */
@Service
public class CustomAdminRoleServiceImpl implements CustomAdminRoleService {

    @Autowired
    private IAdminRoleService adminRoleService;

    @Autowired
    private IAdminUserRoleService adminUserRoleService;
    @Autowired
    private IAdminRolePrivilegeService adminRolePrivilegeService;

    @Autowired
    private IAdminPrivilegeViewService adminPrivilegeViewService;



    @Override
    public CommonPage<AdminRoleDTO> page(String query, Integer pageNum, Integer pageSize) {
        IPage<AdminRole> page = new Page<>();
        page.setSize(pageSize).setCurrent(pageNum);
        Wrapper<AdminRole> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(query)) {
            ((QueryWrapper<AdminRole>) wrapper).like("name", query);
        }
        adminRoleService.page(page, wrapper);
        return new CommonPage<AdminRoleDTO>()
                .setTotalPage(page.getPages())
                .setTotal(page.getTotal())
                .setPageSize(page.getSize())
                .setPageNum(page.getCurrent())
                .setList(AdminRoleDtoTransfer.INSTANCE.toDtoList(page.getRecords()));

    }

    @Override
    public List<AdminRoleDTO> list() {
        List<AdminRole> list = adminRoleService.list();
        return AdminRoleDtoTransfer.INSTANCE.toDtoList(list);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(AdminRoleDTO adminRoleDTO) {
        AdminRole adminRole = AdminRoleDtoTransfer.INSTANCE.toPo(adminRoleDTO);
        adminRole.setId(null);
        adminRoleService.save(adminRole);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(List<Integer> ids) {
        Wrapper<AdminUserRole> wrapper = new QueryWrapper<>();
        ((QueryWrapper<AdminUserRole>) wrapper).in("rid", ids);
        adminUserRoleService.remove(wrapper);
        adminRoleService.removeByIds(ids);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(AdminRoleDTO adminRoleDTO) {
        AdminRole adminRole = AdminRoleDtoTransfer.INSTANCE.toPo(adminRoleDTO);
        adminRoleService.updateById(adminRole);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(Integer id, List<Integer> pids) {
        Wrapper<AdminRolePrivilege> wrapper = new QueryWrapper<>();
        ((QueryWrapper<AdminRolePrivilege>) wrapper).eq("rid",id);
        List<AdminRolePrivilege> old = adminRolePrivilegeService.list(wrapper);
        if(old==null || old.isEmpty()){
            List<AdminRolePrivilege> adminRolePrivilegeList = new LinkedList<>();
            pids.forEach(pid->{
                adminRolePrivilegeList.add(new AdminRolePrivilege().setPid(pid).setRid(id));
            });
            adminRolePrivilegeService.saveBatch(adminRolePrivilegeList);
        }else {
            //删掉一部分(新id列表中不存在但在表中存在)
            List<Integer> idList = new LinkedList<>();
            old.forEach(v -> idList.add(v.getPid()));
            List<Integer> idListBk = new LinkedList<>(idList);
            idList.removeAll(pids);
            if (!idList.isEmpty()) {
                Wrapper<AdminRolePrivilege> wrapper2 = new QueryWrapper<>();
                ((QueryWrapper<AdminRolePrivilege>) wrapper2).in("pid", idList).eq("rid",id);
                adminRolePrivilegeService.remove(wrapper2);

            }
            //添加一部分(在表中不存在但在新id列表中存在)
            pids.removeAll(idListBk);
            if (!pids.isEmpty()) {
                List<AdminRolePrivilege> addList = new LinkedList<>();
                pids.forEach(pid -> addList.add(new AdminRolePrivilege().setRid(id).setPid(pid)));
                adminRolePrivilegeService.saveBatch(addList);
            }
        }
    }

    @Override
    public List<AdminPrivilegeDTO> listPrivilegesOfRole(Integer roleId) {
        List<Integer> idList = listPrivilegeIdsOfRole(roleId);
        Wrapper<AdminPrivilegeView> wrapper2 = new QueryWrapper<>();
        ((QueryWrapper<AdminPrivilegeView>) wrapper2).in("id",idList);
        List<AdminPrivilegeView> list1 = adminPrivilegeViewService.list(wrapper2);
        List<AdminPrivilegeDTO> dtoList = TreeTool.makeTree(AdminPrivilegeDtoTransfer.INSTANCE.toDtoList(list1));
        return dtoList;
    }

    @Override
    public List<Integer> listPrivilegeIdsOfRole(Integer roleId) {
        Wrapper<AdminRolePrivilege> wrapper = new QueryWrapper<>();
        ((QueryWrapper<AdminRolePrivilege>) wrapper).eq("rid",roleId);
        List<AdminRolePrivilege> list = adminRolePrivilegeService.list(wrapper);
        IntStream intStream = list.stream().mapToInt(value -> value.getPid());
        ArrayList<Integer> arrayList = intStream.collect(ArrayList<Integer>::new, List::add, List::addAll);
        return arrayList;
    }

}
